package AOP;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

//声明为一个bean 声明为一个切面   可以通过O
@Order(1)
@Aspect
@Component
public class CaculatorAspect {
	
	//自定义函数表达式
	/**
	 * 定义一个方法表明注入的表达式,一般不在其中加代码了
	 * 使用@Point来声明切入表达式
	 * 后面通知直接使用方法名
	 */
	@Pointcut("execution(void AOP.MyCaculatorInterFace.add(double , double))")
	private void addMethod() {}
	
	//声明一个切面前置方法: 并指定在哪个方法的切面
	@Before("execution(void AOP.MyCaculatorInterFace.add(double , double))")
	//通过JoninPoint可以获取到参数等切面相关信息
	public void beforeMethod(JoinPoint joinPoint) {
		System.out.println("add切面方法之前"); 
		System.out.println("函数名"+joinPoint.getSignature().getName() + "参数:"+joinPoint.getArgs());
	}
	
	//所有方法都触发
//	@Before("execution(void AOP.MyCaculatorInterFace.*(double , double))")
//	public void beforeMul() {
//		// TODO Auto-generated method stub
//		System.out.println("所有方法都触发");
//	}
	
	//后置通知
	@After("execution(void AOP.MyCaculatorInterFace.add(double , double))")
	//通过JoninPoint可以获取到参数等切面相关信息
		public void afterMethod(JoinPoint joinPoint) {
			System.out.println("add切面¸方法之后"); 
			System.out.println("函数名"+joinPoint.getSignature().getName() + "参数:"+joinPoint.getArgs());
		}
	
	//返回通知,正常方法执行完之后才执行 返回通知可以访问到方法的返回值
	@AfterReturning(value="execution(void AOP.MyCaculatorInterFace.add(double , double))",returning="result")
	public void returningMethod(JoinPoint joinPoint,Object result) {
		System.out.println("正常方法执行完之后"+joinPoint.getSignature().getName()+"返回值"+result);
	}
	
	//捕获异常的通知
	@AfterThrowing(value="execution(void AOP.MyCaculatorInterFace.add(double , double))",throwing="e")
	public void afterThrowing(JoinPoint jPoint,Exception e) {
		System.out.println("捕获异常通知");
	}
	
	//环绕通知 需要通知携带PoceedingJoinPoint 类型参数用于控制函数执行 且方法必须有返回值
	@Around(value="addMethod()")
	public Object aroundMethod(ProceedingJoinPoint pjd) {
		Object result = null;
		String methodName = pjd.getSignature().getName();
		//控制执行方法
		try {
			System.out.println("环绕:方法执行之前");
			result = pjd.proceed();
			System.out.println("环绕:方法执行之后");
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
}
